package yxy.game.pm2.module.camptower;

import org.joda.time.DateTime;
import org.joda.time.LocalDate;
import yxy.apple.logger.Logger;
import yxy.apple.util.redisson.RedisException;
import yxy.cherry.data.DataCenter;
import yxy.cherry.data.bean.racetowerdate;
import yxy.game.pm2.bean.Constant;
import yxy.game.pm2.bean.db.dao.MySQLCacheDAO;
import yxy.game.pm2.bean.module.PlayerModule;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

/**
 * @ClassName CampTowerModule
 * @Author jingtao-zheng
 * @Date 2022/8/1 11:18
 * @Version 1.0
 **/
public class CampTowerModule extends PlayerModule {
    // bean===========================================================================
    private Map<Integer, Integer> times = new HashMap<>();// 今天的挑战次数 key-阵营类型 剩余挑战次数
    private Map<Integer, Integer> floor = new HashMap<>();// 完成的层数 key-阵营类型 value层数
    private Map<Integer, Integer> chapter = new HashMap<>();// 正在打的章节 key-阵营类型 value章节数
    private Map<Integer, List<Integer>> starOfTwoChapter;//只存X章的星星数 key-阵营类型 value X章节的星星数
    private DateTime time;// 时间标记,用来刷新每日的挑战次数和购买次数

    private int[] angers;// 保存的怒气
    private Map<Integer, List<Integer>> levelReward;//保存已经领取的奖励
    private Map<Integer, List<Integer>> starReward;//保存已经领取的星星奖励

    public Map<Integer, Integer> getFloor() {
        return floor;
    }

    public void setFloor(Map<Integer, Integer> floor) {
        this.floor = floor;
    }

    public Map<Integer, Integer> getChapter() {
        return chapter;
    }

    public void setChapter(Map<Integer, Integer> chapter) {
        this.chapter = chapter;
    }

    public DateTime getTime() {
        return time;
    }

    public void setTime(DateTime time) {
        this.time = time;
    }

    public Map<Integer, List<Integer>> getLevelReward() {
        return levelReward;
    }

    public void setLevelReward(Map<Integer, List<Integer>> levelReward) {
        this.levelReward = levelReward;
    }

    public int[] getAngers() {
        return angers;
    }

    public void setAngers(int[] angers) {
        this.angers = angers;
    }

    public Map<Integer, Integer> getTimes() {
        return times;
    }

    public void setTimes(Map<Integer, Integer> times) {
        this.times = times;
    }

    public Map<Integer, List<Integer>> getStarOfTwoChapter() {
        return starOfTwoChapter;
    }

    public void setStarOfTwoChapter(Map<Integer, List<Integer>> starOfTwoChapter) {
        this.starOfTwoChapter = starOfTwoChapter;
    }

    public Map<Integer, List<Integer>> getStarReward() {
        return starReward;
    }

    public void setStarReward(Map<Integer, List<Integer>> starReward) {
        this.starReward = starReward;
    }
    // func===========================================================================

    /**
     * 标记时间不同,证明跨天了,需要次数刷新
     */
    public void updateTime() {
        DateTime now = DateTime.now();
        if (getTime() == null || !new LocalDate(now).equals(new LocalDate(getTime()))) {
            try {
                if (tryLock()) {
                    setTime(now);
                    //获取策划配置数据
                    Map<String, racetowerdate> campMap = DataCenter.getAllData(racetowerdate.class);
                    racetowerdate racetowerdate_wei = campMap.get(Constant.WEI_ID);
                    racetowerdate racetowerdate_shu = campMap.get(Constant.SHU_ID);
                    racetowerdate racetowerdate_wu = campMap.get(Constant.WU_ID);
                    racetowerdate racetowerdate_qun = campMap.get(Constant.QUN_ID);
                    Map<Integer, Integer> times = new HashMap<>();// 今天的挑战次数 key-阵营类型 剩余挑战次数
                    times.put(Constant.WEI, racetowerdate_wei.getChance());
                    times.put(Constant.SHU, racetowerdate_shu.getChance());
                    times.put(Constant.WU, racetowerdate_wu.getChance());
                    times.put(Constant.QUN, racetowerdate_qun.getChance());
                    setTimes(times);  //挑战次数
                    setAngers(null);
                    this.set();
                }
            } catch (Exception e) {
            } finally {
                unlock();
            }
        }
        //TODO 红点
        // check();
    }

//    //返回阵营塔剩余挑战次数
//    public int remainTimes() {
//        int maxtimes = fomula.修炼塔每日挑战次数.intValue();
//        int remain = maxtimes - getTimes();
//        return remain;
//    }
//
//    //返回阵营塔剩余购买次数
//    public int remainBuyTimes() {
//        int maxtimes = fomula.修炼塔每日购买次数.intValue();
//        int remain = maxtimes - getBuytimes();
//        return remain;
//    }
//
//    //推送红点功能
//    public void check() {
//        {
//            boolean tip = false;
//            Collection<towerlvreward> datas = DataCenter.getAllData(towerlvreward.class).values();
//            for (towerlvreward data : datas) {
//                int condition = data.getCondition();
//                if (condition > getFloor()) {
//                    continue;
//                }
//                if (getLevelReward().contains(Integer.valueOf(data.getId()))) {
//                    continue;
//                }
//                tip = true;
//                break;
//            }
//            new TipHandle().updateTip(getPlayerCode(), TipType.主城_修炼塔_目标奖励, tip);
//        }
//        new TipHandle().updateTip(getPlayerCode(), TipType.主城_修炼塔_挑战, (remainTimes() > 0));
//    }


    //===================================================redis

    /**
     * 更新星星和章节和层数
     *
     * @param floor   层数
     * @param type    阵营类型
     * @param starnum 该层的星星数
     */
    public boolean updateStarAndChapterAndFloor(int floor, int type, int starnum) {
        //=========================check
        if (floor <= 0) return false;
        //计算传进来的层数所属章节
        int chapter = (floor / Constant.CHAPTER_OF_FLOOR) + (floor % Constant.CHAPTER_OF_FLOOR == 0 ? 0 : 1);
        //判断是否是新章节
        Integer currentChapter = getChapter().get(type);
        boolean isNewChapter = chapter > currentChapter;
        //判断是否有权打这章--第一章,第二章,原来的章节--可以随便打
        if (chapter > Constant.RECORD_FROOL && isNewChapter) {
            //获取排当前章节的前面的第3章的星星总数
            List<Integer> starOfTwoChapter = getStarOfTwoChapter().get(type);
            int starnumtemp = 0;
            for (int i = 0; i < starOfTwoChapter.size() && i < Constant.CHAPTER_OF_FLOOR; i++) {
                Integer star = starOfTwoChapter.get(i);
                starnumtemp += star;
            }
            //如果前面章节没拿到满星
            if (Constant.CHAPTER_OF_FULLSTAR > starnumtemp) {
                return false;
            }
        }
        //=========================handle
        //已删除的章节处理 -- 但是前几章要特殊处理
        if (currentChapter - chapter >= Constant.RECORD_FROOL && currentChapter > Constant.RECORD_FROOL) {
            return true;
        }

        //新章节处理-如果是3章以上需要删除最前面1章节
        if (isNewChapter) {
            if (currentChapter >= Constant.RECORD_FROOL) {
                Map<Integer, List<Integer>> allAtarOfTwoChapter = getStarOfTwoChapter();
                List<Integer> starOfTwoChapter = allAtarOfTwoChapter.get(type);
                List<Integer> newStarOfTwoChapter = starOfTwoChapter.subList(Constant.CHAPTER_OF_FLOOR, starOfTwoChapter.size());
                allAtarOfTwoChapter.put(type, newStarOfTwoChapter);
            }
            //更新 新层数 新章节
            updateNewFloorNewChapter(floor, type, starnum, chapter);
            set();
            return true;
        }

        //老章节处理-判断是不是新层数
        Integer currentFloor = getFloor().get(type);
        if (floor > currentFloor) {
            //更新 新层数
            updateNewFloor(floor, type, starnum);
            set();
            return true;
        }

        //老章节处理-判断是不是未被删除的老章节
        if (currentChapter - chapter <= Constant.RECORD_FROOL - 1) {
            //更新 老层数
            updateOldFloor(floor, type, starnum, chapter, currentChapter);
            set();
            return true;
        }
        return true;
    }

    /**
     * 更新 新层数 新章节
     *
     * @param floor   新层
     * @param type    类型
     * @param starnum 星星
     * @param chapter 新章节
     */
    private void updateNewFloorNewChapter(int floor, int type, int starnum, int chapter) {
        //加星星
        Map<Integer, List<Integer>> allStarOfTwoChapter = getStarOfTwoChapter();
        List<Integer> starOfTwoChapter = allStarOfTwoChapter.get(type);
        starOfTwoChapter.add(starnum);
        setStarOfTwoChapter(allStarOfTwoChapter);
        //改层数
        Map<Integer, Integer> allFloor = getFloor();
        allFloor.put(type, floor);
        setFloor(allFloor);
        //改章节数
        Map<Integer, Integer> allChapter = getChapter();
        allChapter.put(type, chapter);
        setChapter(allChapter);
        //减次数
        Map<Integer, Integer> allTimes = getTimes();
        Integer times = allTimes.get(type);
        allTimes.put(type, times - 1);
    }

    /**
     * 更新 新层数
     *
     * @param floor   新层
     * @param type    类型
     * @param starnum 星星
     */
    private void updateNewFloor(int floor, int type, int starnum) {
        //加星星
        Map<Integer, List<Integer>> allStarOfTwoChapter = getStarOfTwoChapter();
        List<Integer> starOfTwoChapter = allStarOfTwoChapter.get(type);
        starOfTwoChapter.add(starnum);
        setStarOfTwoChapter(allStarOfTwoChapter);
        //改层数
        Map<Integer, Integer> allFloor = getFloor();
        allFloor.put(type, floor);
        setFloor(allFloor);
        //减次数
        Map<Integer, Integer> allTimes = getTimes();
        Integer times = allTimes.get(type);
        allTimes.put(type, times - 1);
    }


    /**
     * 更新 老层数
     *
     * @param floor          层
     * @param type           类型
     * @param starnum        星星
     * @param chapter        传进来的层数所属章节
     * @param currentChapter 当前章节
     */
    private void updateOldFloor(int floor, int type, int starnum, int chapter, int currentChapter) {
        //下标因子
        int indexFactorX = 0;
        int i = currentChapter - chapter;
        indexFactorX = Constant.RECORD_FROOL - i - 1;
        int indexFactorY = (floor - 1) % Constant.CHAPTER_OF_FLOOR;
        //计算下标
        int index = Constant.CHAPTER_OF_FLOOR * indexFactorX + indexFactorY;
        //前几章下标特殊处理
        if (currentChapter < Constant.RECORD_FROOL) {
            index = Constant.CHAPTER_OF_FLOOR * (chapter - 1) + indexFactorY;
        }
        //改星星+大于原来的星星数才改
        Map<Integer, List<Integer>> allStarOfTwoChapter = getStarOfTwoChapter();
        List<Integer> starOfTwoChapter = allStarOfTwoChapter.get(type);
        Integer oldStarNum = starOfTwoChapter.get(index);
        if (oldStarNum < starnum) {
            starOfTwoChapter.set(index, starnum);
        }
        setStarOfTwoChapter(allStarOfTwoChapter);
        //减次数
        Map<Integer, Integer> allTimes = getTimes();
        Integer times = allTimes.get(type);
        allTimes.put(type, times - 1);
    }

    /**
     * 检查是否能打该层
     *
     * @return
     */
    public boolean checkCanPlay(int floor, int type) {
        if (floor <= 0) return false;
        //计算传进来的层数所属章节
        int chapter = (floor / Constant.CHAPTER_OF_FLOOR) + (floor % Constant.CHAPTER_OF_FLOOR == 0 ? 0 : 1);
        //判断是否是新章节
        Integer currentChapter = getChapter().get(type);
        boolean isNewChapter = chapter > currentChapter;
        //判断是否有权打这章--第一章,第二章,第三章,原来的章节--可以随便打
        if (chapter > Constant.RECORD_FROOL && isNewChapter) {
            //获取排当前章节的前面的第2章的星星总数
            List<Integer> starOfTwoChapter = getStarOfTwoChapter().get(type);
            int starnum = 0;
            for (int i = 0; i < starOfTwoChapter.size() && i < Constant.CHAPTER_OF_FLOOR; i++) {
                Integer star = starOfTwoChapter.get(i);
                starnum += star;
            }
            //如果前面章节没拿到满星
            if (Constant.CHAPTER_OF_FULLSTAR > starnum) {
                return false;
            }
        }
        return true;
    }

    //===============================redis
    protected static Logger logger = Logger.create(CampTowerModule.class);
    //存储到数据库的方法
    public static void saveToDB(String playerCode) {
        try {
            logger.info("阵营塔保存玩家code:%s",playerCode);
            String key = key(playerCode);
            if (touchBucket(key).isExists()) {
                CampTowerModule towerModule = getv(key(playerCode));
                if (towerModule != null) MySQLCacheDAO.setV(key, towerModule);
            }
        } catch (Exception e) {
            logger.error("阵营塔保存出错:玩家code:%s",playerCode);
            e.printStackTrace();
        }

    }

    //从redis移走数据的操作
    public static void removeAllFromRedis(String playerCode) {
        try {
            logger.info("阵营塔移除redis玩家code:%s",playerCode);
            touchBucket(key(playerCode)).delete();
        } catch (RedisException e) {
            logger.error("阵营塔移除redis玩家code:%s",playerCode);
            e.printStackTrace();
        }
    }

    public void set() {
        try {
            setv(key(getPlayerCode()), this);
            //TODO 红点
            // check();
        } catch (RedisException e) {
            e.printStackTrace();
        }
    }

    static public CampTowerModule get(String playerCode) {
        try {
            CampTowerModule module = getv(key(playerCode));
            if (module == null) {
                module = MySQLCacheDAO.getV(key(playerCode), CampTowerModule.class);
                if (module != null) {
                    module.set();
                }//把数据同步到redis
            }
            if (module == null) {
                module = create(playerCode);
            }
            if (module == null) return null;

            module.updateTime();
            return module;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    //初始化阵营塔module
    static private CampTowerModule create(String playerCode) {
        DateTime now = DateTime.now();
        CampTowerModule module = new CampTowerModule();
        module.setPlayerCode(playerCode);
        module.setTime(now); //标记初始化时间
        //获取策划配置数据
        Map<String, racetowerdate> campMap = DataCenter.getAllData(racetowerdate.class);
        racetowerdate racetowerdate_wei = campMap.get(Constant.WEI_ID);
        racetowerdate racetowerdate_shu = campMap.get(Constant.SHU_ID);
        racetowerdate racetowerdate_wu = campMap.get(Constant.WU_ID);
        racetowerdate racetowerdate_qun = campMap.get(Constant.QUN_ID);
        Map<Integer, Integer> times = new HashMap<>();// 今天的挑战次数 key-阵营类型 剩余挑战次数
        times.put(Constant.WEI, racetowerdate_wei.getChance());
        times.put(Constant.SHU, racetowerdate_shu.getChance());
        times.put(Constant.WU, racetowerdate_wu.getChance());
        times.put(Constant.QUN, racetowerdate_qun.getChance());
        module.setTimes(times);  //挑战次数
        Map<Integer, Integer> floor = new HashMap<>();// 完成的层数 key-阵营类型 value层数
        Map<Integer, Integer> chapter = new HashMap<>();// 完成的层数 key-阵营类型 value章节数
        floor.put(Constant.WEI, 0);
        floor.put(Constant.SHU, 0);
        floor.put(Constant.WU, 0);
        floor.put(Constant.QUN, 0);
        chapter.put(Constant.WEI, 1);
        chapter.put(Constant.SHU, 1);
        chapter.put(Constant.WU, 1);
        chapter.put(Constant.QUN, 1);
        module.setFloor(floor);//层数
        module.setChapter(chapter);//章节数
        Map<Integer, List<Integer>> chapterAndStar = new HashMap<>();
        chapterAndStar.put(Constant.WEI, new LinkedList<Integer>());
        chapterAndStar.put(Constant.SHU, new LinkedList<Integer>());
        chapterAndStar.put(Constant.WU, new LinkedList<Integer>());
        chapterAndStar.put(Constant.QUN, new LinkedList<Integer>());
        module.setStarOfTwoChapter(chapterAndStar);
        //初始化奖励
        Map<Integer, List<Integer>> levelReward = new HashMap<>();
        levelReward.put(Constant.WEI, new LinkedList<Integer>());
        levelReward.put(Constant.SHU, new LinkedList<Integer>());
        levelReward.put(Constant.WU, new LinkedList<Integer>());
        levelReward.put(Constant.QUN, new LinkedList<Integer>());
        module.setLevelReward(levelReward);
        //初始化星星奖励
        Map<Integer, List<Integer>> starReward = new HashMap<>();
        starReward.put(Constant.WEI, new LinkedList<Integer>());
        starReward.put(Constant.SHU, new LinkedList<Integer>());
        starReward.put(Constant.WU, new LinkedList<Integer>());
        starReward.put(Constant.QUN, new LinkedList<Integer>());
        module.setStarReward(starReward);
        module.set();
        return module;
    }

    private static String key(String playerCode) {
        return String.format("PLAYER:%s:MODULE:CAMPTOWER", playerCode);
    }

    @Override
    public String lockKey() {
        return String.format("lock:%s", key(getPlayerCode()));
    }
}
